/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/*******************************************************************************
    FILE NAME:		ecanioctl.h

    PROJECT:		Linux ECAN527/1000 driver, library, and sample programs

    FILE DESCRIPTION:	This header file contains mid-level ioctl definitions.

    Copyright (c) 2004 RTD Embedded Technologies, Inc.

    For driver version, compiler, and target information, please refer to the
    file README.TXT.
*******************************************************************************/
#ifndef  _ECAN_IOCTL_H
# define _ECAN_IOCTL_H
//#define  __cplusplus // WTF?????????????????????!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/*
Notes:

1. hardware-specific functions should provide stub function
   with success return status for hardware without this features
   (lamerface compatibility requirements).

2. bool DontQueueUse member of interface structs is input parameter:
	true  - get/set hardware data/status w/o queue handling
	false - have deal with queue items
*/


# include <ecan_types.h>	/* bool, uNN_t, size_t */
# include <string.h>		/* memset() */
# include <ecanbaseioctl.h>	/* low-level */


enum BitRates {
	R1000000,
	R800000,
	R500000,
	R400000,
	R250000,
	R200000,
	R160000,
	R125000,
	R100000,
	R80000,
	R62500,
	R50000,
	R40000,
	R31250,
	R25000,
	R20000,
	R16000,
	R15625,
	R12500,
	R10000,
	R8000,
	R7813,		// (actually 7812.5)
	R6150,
	R5000
};


# ifndef       HANDLE
   typedef int HANDLE; /* MS Windows compatibility - unix "file descriptor" */
#  define      HANDLE HANDLE
# endif


/* device-independent event bits */
enum
{
 Int_RI_Bit  = RTD_ECAN_EVENT_RECEIVE         , // receive interrupt bit
 Int_TI_Bit  = RTD_ECAN_EVENT_TRANSMIT        , // transmit interrupt bit
 Int_EI_Bit  = RTD_ECAN_EVENT_ERROR_WARN_LIMIT, // error warning interrupt bit
 Int_DOI_Bit = RTD_ECAN_EVENT_DATA_OVERRUN    , // data overrun interrupt bit
 Int_WUI_Bit = RTD_ECAN_EVENT_WAKE_UP         , // wake-up interrupt bit
 Int_EPI_Bit = RTD_ECAN_EVENT_ERROR_PASSIVE   , // error passive interrupt bit
 Int_ALI_Bit = RTD_ECAN_EVENT_ARBITRATION_LOST, // arbitration lost interrupt bit
 Int_BEI_Bit = RTD_ECAN_EVENT_BUS_ERROR         // bus error interrupt bit
};


typedef struct _ECAN_STATUS_STRUCTURE
{
	bool BusOff;	/* bus off                                  */
	bool Warning;	/* Error Warning limit reached              */
	bool WakeUp;	/* not used in Ecan1000                     */
	bool TXOK;	/* Transmission Complete (Ecan1000)         */
	bool RXOK;	/* Receive Message Successfully (!Ecan1000) */
	bool TS;	/* Transmit Status                          */
	bool RS;	/* Receive Status                           */
	bool TBS;	/* Transmit Buffer Status                   */
	bool DOS;	/* Data Overrun Status                      */
	bool RBS;	/* Receive Buffer Status                    */
	u8_t Arbitration; /* Arbitration lost capture register      */
	u8_t ErrorCode;   /* Last Error Code register               */
	bool DontQueueUse;

#ifdef __cplusplus
	_ECAN_STATUS_STRUCTURE()
	    : BusOff(false), Warning(false), WakeUp(false)
	    ,  TXOK(false),    RXOK(false),     TS(false), RS(false)
	    ,   TBS(false),     DOS(false),    RBS(false)
	    , Arbitration(false), ErrorCode(false), DontQueueUse(false)
	{
	}
#endif	/* __cplusplus */

} ECAN_STATUS_STRUCTURE, *PECAN_STATUS_STRUCTURE;


/* external message queue item structure */
typedef struct _ECAN_MESSAGE_STRUCTURE
{
	u8_t	Channel;
		/* Ecan527 only:
			0     - Default Transmitting or Defaullt Receiving
			        of Message Object
			1..15 - Message Object by number */

	bool	Extended;	/* Extended Frame Format    */
	bool	Remote;		/* Remote Frame request
		(Attention for Ecan527! this value = inverse direction bit) */
	u8_t	ID_0;		/* Identifier octet 0 */
	u8_t	ID_1;		/* Identifier octet 1 */
	u8_t	ID_2;		/* Identifier octet 2 */
	u8_t	ID_3;		/* Identifier octet 3 */
	u8_t	DataLength;	/* Data Length Code (DLC) (0..8) */
	u8_t	Data[8];	/* Data Octets */
	bool	NextMsg;	/* out: the next message available in a queue */
	bool	DontQueueUse;

#ifdef __cplusplus
	void Clear()	{ memset( this, 0, sizeof(*this) ); }

	_ECAN_MESSAGE_STRUCTURE()	{ Clear(); }


	/* Identifiers helper functions */

	u32_t GetID()
	{
		const u8_t id[4] = { ID_0, ID_1, ID_2, ID_3 };
		return rtd_ecan_convert_octets_to_id(Extended, id);
	}

	void SetID(u32_t ID)
	{
		u8_t id[4] = { 0, 0, 0, 0 };
		rtd_ecan_convert_id_to_octets(Extended, ID, id);
		ID_0 = id[0]; ID_1 = id[1]; ID_2 = id[2]; ID_3 = id[3];
	}
#endif	/* __cplusplus */

} ECAN_MESSAGE_STRUCTURE, *PECAN_MESSAGE_STRUCTURE;


/* + Ecan527 only (Multiple Messsage Objects) */

typedef enum MESSAGE_OBJECT_STATE
{
    MO_DISABLED        = RTD_ECAN_MO_DISABLED,
    MO_RECEIVE         = RTD_ECAN_MO_RECEIVE,	/* receive */
    MO_TRANSMIT        = RTD_ECAN_MO_TRANSMIT,	/* transmit */
    MO_REMOTE_TRANSMIT = RTD_ECAN_MO_REMOTE_TRANSMIT
    	/* transmit after receiving remote frame whith the same ID */

} MESSAGE_OBJECT_STATE;


typedef struct _ECAN_MESSAGE_OBJECT_SETUP_STRUCTURE
{
	u8_t	Channel;
		/* Ecan527 only:
			0     - Default Transmitting or Defaullt Receiving
			        of Message Object
			1..15 - Message Object by number */

	MESSAGE_OBJECT_STATE State;

	bool	Valid;		/* enable Message Object after setup                 */
	bool	Extended;	/* Extended Frame Format                             */
	bool	RXIE;		/* Enable  Receive Message Interrupt for this object */
	bool	TXIE;		/* Enable Transmit Message Interrupt for this object */
	bool	DontQueueUse;	/* if FALSE for MO_TRANSMIT, then changes
					Default Transmitting Object to this          */
	bool	MakeDefault;	/* set msg obj 'Channel' to be default for rx/tx     */
	u8_t	ID_0;		/* Identifier octet 0 */
	u8_t	ID_1;		/* Identifier octet 1 */
	u8_t	ID_2;		/* Identifier octet 2 */
	u8_t	ID_3;		/* Identifier octet 3 */

#ifdef __cplusplus
	void Clear()	{ memset( this, 0, sizeof(*this) ); }

	_ECAN_MESSAGE_OBJECT_SETUP_STRUCTURE()	{ Clear(); }


	/* Identifiers helper functions */

	u32_t GetID()
	{
		const u8_t id[4] = { ID_0, ID_1, ID_2, ID_3 };
		return rtd_ecan_convert_octets_to_id(Extended, id);
	}

	void SetID(u32_t ID)
	{
		u8_t id[4] = { 0, 0, 0, 0 };
		rtd_ecan_convert_id_to_octets(Extended, ID, id);
		ID_0 = id[0]; ID_1 = id[1]; ID_2 = id[2]; ID_3 = id[3];
	}
#endif	/* __cplusplus */

} ECAN_MESSAGE_OBJECT_SETUP_STRUCTURE, *PECAN_MESSAGE_OBJECT_SETUP_STRUCTURE;

/* - Ecan527 only (Multiple Messsage Objects) */


typedef struct _ECAN_FILTER_STRUCTURE
{
	u8_t AC0; /* Acceptance Code Reg 0 (For Ecan527 - Not used) */
	u8_t AC1; /* Acceptance Code Reg 1 (For Ecan527 - Not used) */
	u8_t AC2; /* Acceptance Code Reg 2 (For Ecan527 - Not used) */
	u8_t AC3; /* Acceptance Code Reg 3 (For Ecan527 - Not used) */
	u8_t AM0; /* Acceptance Mask Reg 0 (For Ecan527 - Global Mask Standard (Addr-06H)) */
	u8_t AM1; /* Acceptance Mask Reg 1 (For Ecan527 - Global Mask Standard (Addr-07H)) */
	u8_t AM2; /* Acceptance Mask Reg 2 (For Ecan527 - Not used) */
	u8_t AM3; /* Acceptance Mask Reg 3 (For Ecan527 - Not used) */

	/* Not used in the Ecan1000 */
	u8_t ME0; /* Global Mask Extended (Address-08H) */
	u8_t ME1; /* Global Mask Extended (Address-09H) */
	u8_t ME2; /* Global Mask Extended (Address-0AH) */
	u8_t ME3; /* Global Mask Extended (Address-0BH) */
	u8_t MM0; /* Message 15 mask      (Address 0CH) */
	u8_t MM1; /* Message 15 mask      (Address 0DH) */
	u8_t MM2; /* Message 15 mask      (Address 0EH) */
	u8_t MM3; /* Message 15 mask      (Address 0FH) */

	bool MMIsExtended; /* Message 15 mask is for extended frames */
	bool DualFilter; /* For Ecan1000 only */
	bool DontQueueUse;

#ifdef __cplusplus
	void Clear()
	{
		AC0 = AC1 = AC2 = AC3 = 0x00;
		AM0 = AM1 = AM2 = AM3 = 0xff;
		ME0 = ME1 = ME2 = ME3 = 0xff;
		MM0 = MM1 = MM2 = MM3 = 0xff;
		DualFilter = DontQueueUse = false;
	}

	_ECAN_FILTER_STRUCTURE() { Clear(); }


	/* + For Ecan 527 */
	void SetExtended(u32_t ID)	/* extended filter */
	{
		u8_t id[4] = { 0, 0, 0, 0 };
		rtd_ecan_convert_id_to_octets(true, ID, id);
		ME0 = id[0]; ME1 = id[1]; ME2 = id[2]; ME3 = id[3];
	}

	u32_t GetExtended()
	{
		const u8_t id[4] = { ME0, ME1, ME2, ME3 };
		return rtd_ecan_convert_octets_to_id(true, id);
	}

	void SetMessage15Mask(u32_t ID, bool ExtendedFrame)
	{
		u8_t id[4] = { 0, 0, 0, 0 };
		rtd_ecan_convert_id_to_octets(ExtendedFrame, ID, id);
		MM0 = id[0]; MM1 = id[1]; MM2 = id[2]; MM3 = id[3];
		MMIsExtended = ExtendedFrame;
	}

	u32_t GetMessage15Mask(bool ExtendedFrame)
	{
		const u8_t id[4] = { MM0, MM1, MM2, MM3 };
		return rtd_ecan_convert_octets_to_id(ExtendedFrame, id);
	}
	/* - For Ecan 527 */


	void SetAcceptCode(u32_t ID, bool LongFormat=true)
	{
		u8_t id[4] = { 0, 0, 0, 0 };
		rtd_ecan_convert_id_to_octets(LongFormat, ID, id);
		AC0 = id[0]; AC1 = id[1]; AC2 = id[2]; AC3 = id[3];
	}

	u32_t GetAcceptCode(bool LongFormat=true)
	{
		const u8_t id[4] = { AC0, AC1, AC2, AC3 };
		return rtd_ecan_convert_octets_to_id(LongFormat, id);
	}

	void SetAcceptMask(u32_t ID, bool LongFormat=true, bool Ecan527=false)
	{
		if(Ecan527)
			SetExtended(ID);
		else
		{
			u8_t id[4] = { 0, 0, 0, 0 };
			rtd_ecan_convert_id_to_octets(LongFormat, ID, id);
			AM0 = id[0]; AM1 = id[1]; AM2 = id[2]; AM3 = id[3];
		}
	}

	u32_t GetAcceptMask(bool LongFormat=true, bool Ecan527=false)
	{
		if(Ecan527)
			return GetExtended();
		else
		{
			const u8_t id[4] = { AM0, AM1, AM2, AM3 };
			return rtd_ecan_convert_octets_to_id(LongFormat, id);
		}
	}

#endif	/* __cplusplus */

} ECAN_FILTER_STRUCTURE, *PECAN_FILTER_STRUCTURE;


#endif /* _ECAN_IOCTL_H */
